package edu.arizona.sista.learn.model.inferences;

import java.util.ArrayList;
import java.util.List;

/**
 * A simple model of predicates
 */
public class Predicate {
	private String _name;
	private Object[] _variables; //variables can be Strings or Predicates
	private double weight; // not sure whether this will be useful 
	
	public Predicate(String name, Object[] variables) {
		_name = name;
		_variables = variables;
	}
	
	public Predicate(String expression) {

		//Format: pred(X_1, ..., X_n)
		//Each variable X_i can be a predicate

		//Name
		_name = expression.substring(0, expression.indexOf('('));
		
		//Variables
		int beginIndex = expression.indexOf('(') + 1;
		int endIndex = closingIndex(expression, beginIndex - 1);
		
		List<String> tokens = getTokens(expression.substring(beginIndex, endIndex));
		_variables = new Object[tokens.size()];
		for (int i = 0; i < tokens.size(); i++){
			String s = tokens.get(i);
			if (s.contains("(")) _variables[i] = new Predicate(s);
			else _variables[i] = s;
		}
	}
	
	private List<String> getTokens(String s) {
		List<String> l = new ArrayList<String>();
		int a = 0;
		for (int i = 0; i < s.length(); i++) {
			if (s.charAt(i) == '(') i = closingIndex(s, i);
			else if (s.charAt(i) == ',') {
				String m = s.substring(a, i);
				l.add(m.trim());
				a = i + 1;
				i++;
			}
		}
		String m = s.substring(a, s.length());
		l.add(m.trim());
		return l;
	}
		
	private int closingIndex(String s, int a) {
		if (s.charAt(a) != '(')	return -1;
		int cpt = 0;
		for (int i = a; i < s.length(); i++) {
			char c = s.charAt(i);
			if (c == '(') cpt++;
			if (c == ')') cpt--;
			if (cpt == 0) return i;
		}
		return -1;
	}

	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer(_name + "(");
		for(int i = 0; i < _variables.length - 1; i++) sb.append(_variables[i] + ", "); 
		sb.append(_variables[_variables.length - 1] + ")");
		return sb.toString();
	}
	
	public boolean equals(Predicate p) {
		if (!p._name.equals(_name) || p._variables.length != _variables.length) return false;
		for (int i = 0; i < _variables.length; i++)
			if (!_variables[i].equals(p._variables[i])) return false;
		return true;
	}
}
